<?php
// +----------------------------------------------------------------------
// | OneThink [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013 http://www.onethink.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: 麦当苗儿 <zuojiazi@vip.qq.com> <http://www.zjzit.cn>
// +----------------------------------------------------------------------

// OneThink常量定义
const ONETHINK_VERSION    = '1.1.141212';
const ONETHINK_ADDON_PATH = './Addons/';

/**
 * 系统公共库文件
 * 主要定义系统公共函数库
 */

/**
 * 检测用户是否登录
 * @return integer 0-未登录，大于0-当前登录用户ID
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function is_login(){
    $user = session('user_auth');
    if (empty($user)) {
        return 0;
    } else {
        return session('user_auth_sign') == data_auth_sign($user) ? $user['uid'] : 0;
    }
}

/**
 * 检测当前用户是否为管理员
 * @return boolean true-管理员，false-非管理员
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function is_administrator($uid = null){
    $uid = is_null($uid) ? is_login() : $uid;
    return $uid && (intval($uid) === C('USER_ADMINISTRATOR'));
}

/**
 * 字符串转换为数组，主要用于把分隔符调整到第二个参数
 * @param  string $str  要分割的字符串
 * @param  string $glue 分割符
 * @return array
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function str2arr($str, $glue = ','){
    return explode($glue, $str);
}

/**
 * 数组转换为字符串，主要用于把分隔符调整到第二个参数
 * @param  array  $arr  要连接的数组
 * @param  string $glue 分割符
 * @return string
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function arr2str($arr, $glue = ','){
    return implode($glue, $arr);
}

/**
 * 字符串截取，支持中文和其他编码
 * @static
 * @access public
 * @param string $str 需要转换的字符串
 * @param string $start 开始位置
 * @param string $length 截取长度
 * @param string $charset 编码格式
 * @param string $suffix 截断显示字符
 * @return string
 */
function msubstr($str, $start=0, $length, $charset="utf-8", $suffix=true) {
    if(function_exists("mb_substr"))
        $slice = mb_substr($str, $start, $length, $charset);
    elseif(function_exists('iconv_substr')) {
        $slice = iconv_substr($str,$start,$length,$charset);
        if(false === $slice) {
            $slice = '';
        }
    }else{
        $re['utf-8']   = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
        $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
        $re['gbk']    = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
        $re['big5']   = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
        preg_match_all($re[$charset], $str, $match);
        $slice = join("",array_slice($match[0], $start, $length));
    }
    return $suffix ? $slice.'...' : $slice;
}

/**
 * 系统加密方法
 * @param string $data 要加密的字符串
 * @param string $key  加密密钥
 * @param int $expire  过期时间 单位 秒
 * @return string
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function think_encrypt($data, $key = '', $expire = 0) {
    $key  = md5(empty($key) ? C('DATA_AUTH_KEY') : $key);
    $data = base64_encode($data);
    $x    = 0;
    $len  = strlen($data);
    $l    = strlen($key);
    $char = '';

    for ($i = 0; $i < $len; $i++) {
        if ($x == $l) $x = 0;
        $char .= substr($key, $x, 1);
        $x++;
    }

    $str = sprintf('%010d', $expire ? $expire + time():0);

    for ($i = 0; $i < $len; $i++) {
        $str .= chr(ord(substr($data, $i, 1)) + (ord(substr($char, $i, 1)))%256);
    }
    return str_replace(array('+','/','='),array('-','_',''),base64_encode($str));
}

/**
 * 系统解密方法
 * @param  string $data 要解密的字符串 （必须是think_encrypt方法加密的字符串）
 * @param  string $key  加密密钥
 * @return string
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function think_decrypt($data, $key = ''){
    $key    = md5(empty($key) ? C('DATA_AUTH_KEY') : $key);
    $data   = str_replace(array('-','_'),array('+','/'),$data);
    $mod4   = strlen($data) % 4;
    if ($mod4) {
        $data .= substr('====', $mod4);
    }
    $data   = base64_decode($data);
    $expire = substr($data,0,10);
    $data   = substr($data,10);

    if($expire > 0 && $expire < time()) {
        return '';
    }
    $x      = 0;
    $len    = strlen($data);
    $l      = strlen($key);
    $char   = $str = '';

    for ($i = 0; $i < $len; $i++) {
        if ($x == $l) $x = 0;
        $char .= substr($key, $x, 1);
        $x++;
    }

    for ($i = 0; $i < $len; $i++) {
        if (ord(substr($data, $i, 1))<ord(substr($char, $i, 1))) {
            $str .= chr((ord(substr($data, $i, 1)) + 256) - ord(substr($char, $i, 1)));
        }else{
            $str .= chr(ord(substr($data, $i, 1)) - ord(substr($char, $i, 1)));
        }
    }
    return base64_decode($str);
}

/**
 * 数据签名认证
 * @param  array  $data 被认证的数据
 * @return string       签名
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function data_auth_sign($data) {
    //数据类型检测
    if(!is_array($data)){
        $data = (array)$data;
    }
    ksort($data); //排序
    $code = http_build_query($data); //url编码并生成query字符串
    $sign = sha1($code); //生成签名
    return $sign;
}

/**
 * 对查询结果集进行排序
 * @access public
 * @param array $list 查询结果
 * @param string $field 排序的字段名
 * @param array $sortby 排序类型
 * asc正向排序 desc逆向排序 nat自然排序
 * @return array
 */
function list_sort_by($list,$field, $sortby='asc') {
    if(is_array($list)){
        $refer = $resultSet = array();
        foreach ($list as $i => $data)
            $refer[$i] = &$data[$field];
        switch ($sortby) {
            case 'asc': // 正向排序
                asort($refer);
                break;
            case 'desc':// 逆向排序
                arsort($refer);
                break;
            case 'nat': // 自然排序
                natcasesort($refer);
                break;
        }
        foreach ( $refer as $key=> $val)
            $resultSet[] = &$list[$key];
        return $resultSet;
    }
    return false;
}

/**
 * 把返回的数据集转换成Tree
 * @param array $list 要转换的数据集
 * @param string $pid parent标记字段
 * @param string $level level标记字段
 * @return array
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function list_to_tree($list, $pk='id', $pid = 'pid', $child = '_child', $root = 0) {
    // 创建Tree
    $tree = array();
    if(is_array($list)) {
        // 创建基于主键的数组引用
        $refer = array();
        foreach ($list as $key => $data) {
            $refer[$data[$pk]] =& $list[$key];
        }
        foreach ($list as $key => $data) {
            // 判断是否存在parent
            $parentId =  $data[$pid];
            if ($root == $parentId) {
                $tree[] =& $list[$key];
            }else{
                if (isset($refer[$parentId])) {
                    $parent =& $refer[$parentId];
                    $parent[$child][] =& $list[$key];
                }
            }
        }
    }
    return $tree;
}

/**
 * 将list_to_tree的树还原成列表
 * @param  array $tree  原来的树
 * @param  string $child 孩子节点的键
 * @param  string $order 排序显示的键，一般是主键 升序排列
 * @param  array  $list  过渡用的中间数组，
 * @return array        返回排过序的列表数组
 * @author yangweijie <yangweijiester@gmail.com>
 */
function tree_to_list($tree, $child = '_child', $order='id', &$list = array()){
    if(is_array($tree)) {
        foreach ($tree as $key => $value) {
            $reffer = $value;
            if(isset($reffer[$child])){
                unset($reffer[$child]);
                tree_to_list($value[$child], $child, $order, $list);
            }
            $list[] = $reffer;
        }
        $list = list_sort_by($list, $order, $sortby='asc');
    }
    return $list;
}

/**
 * 格式化字节大小
 * @param  number $size      字节数
 * @param  string $delimiter 数字和单位分隔符
 * @return string            格式化后的带单位的大小
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function format_bytes($size, $delimiter = '') {
    $units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB');
    for ($i = 0; $size >= 1024 && $i < 5; $i++) $size /= 1024;
    return round($size, 2) . $delimiter . $units[$i];
}

/**
 * 设置跳转页面URL
 * 使用函数再次封装，方便以后选择不同的存储方式（目前使用cookie存储）
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function set_redirect_url($url){
    cookie('redirect_url', $url);
}

/**
 * 获取跳转页面URL
 * @return string 跳转页URL
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function get_redirect_url(){
    $url = cookie('redirect_url');
    return empty($url) ? __APP__ : $url;
}

/**
 * 处理插件钩子
 * @param string $hook   钩子名称
 * @param mixed $params 传入参数
 * @return void
 */
function hook($hook,$params=array()){
    \Think\Hook::listen($hook,$params);
}

/**
 * 获取插件类的类名
 * @param strng $name 插件名
 */
function get_addon_class($name){
    $class = "Addons\\{$name}\\{$name}Addon";
    return $class;
}

/**
 * 获取插件类的配置文件数组
 * @param string $name 插件名
 */
function get_addon_config($name){
    $class = get_addon_class($name);
    if(class_exists($class)) {
        $addon = new $class();
        return $addon->getConfig();
    }else {
        return array();
    }
}

/**
 * 插件显示内容里生成访问插件的url
 * @param string $url url
 * @param array $param 参数
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function addons_url($url, $param = array()){
    $url        = parse_url($url);
    $case       = C('URL_CASE_INSENSITIVE');
    $addons     = $case ? parse_name($url['scheme']) : $url['scheme'];
    $controller = $case ? parse_name($url['host']) : $url['host'];
    $action     = trim($case ? strtolower($url['path']) : $url['path'], '/');

    /* 解析URL带的参数 */
    if(isset($url['query'])){
        parse_str($url['query'], $query);
        $param = array_merge($query, $param);
    }

    /* 基础参数 */
    $params = array(
        '_addons'     => $addons,
        '_controller' => $controller,
        '_action'     => $action,
    );
    $params = array_merge($params, $param); //添加额外参数

    return U('Addons/execute', $params);
}

/**
 * 时间戳格式化
 * @param int $time
 * @return string 完整的时间显示
 * @author huajie <banhuajie@163.com>
 */
function time_format($time = NULL,$format='Y-m-d H:i'){
    $time = $time === NULL ? NOW_TIME : intval($time);
    return date($format, $time);
}

/**
 * 根据用户ID获取用户名
 * @param  integer $uid 用户ID
 * @return string       用户名
 */
function get_username($uid = 0){
    static $list;
    if(!($uid && is_numeric($uid))){ //获取当前登录用户名
        return session('user_auth.username');
    }

    /* 获取缓存数据 */
    if(empty($list)){
        $list = S('sys_active_user_list');
    }

    /* 查找用户信息 */
    $key = "u{$uid}";
    if(isset($list[$key])){ //已缓存，直接使用
        $name = $list[$key];
    } else { //调用接口获取用户信息
        $User = new User\Api\UserApi();
        $info = $User->info($uid);
        if($info && isset($info[1])){
            $name = $list[$key] = $info[1];
            /* 缓存用户 */
            $count = count($list);
            $max   = C('USER_MAX_CACHE');
            while ($count-- > $max) {
                array_shift($list);
            }
            S('sys_active_user_list', $list);
        } else {
            $name = '';
        }
    }
    return $name;
}

/**
 * 根据用户ID获取用户昵称
 * @param  integer $uid 用户ID
 * @return string       用户昵称
 */
function get_nickname($uid = 0){
    static $list;
    if(!($uid && is_numeric($uid))){ //获取当前登录用户名
        return session('user_auth.username');
    }

    /* 获取缓存数据 */
    if(empty($list)){
        $list = S('sys_user_nickname_list');
    }

    /* 查找用户信息 */
    $key = "u{$uid}";
    if(isset($list[$key])){ //已缓存，直接使用
        $name = $list[$key];
    } else { //调用接口获取用户信息
        $info = M('Member')->field('nickname')->find($uid);
        if($info !== false && $info['nickname'] ){
            $nickname = $info['nickname'];
            $name = $list[$key] = $nickname;
            /* 缓存用户 */
            $count = count($list);
            $max   = C('USER_MAX_CACHE');
            while ($count-- > $max) {
                array_shift($list);
            }
            S('sys_user_nickname_list', $list);
        } else {
            $name = '';
        }
    }
    return $name;
}

/**
 * 获取分类信息并缓存分类
 * @param  integer $id    分类ID
 * @param  string  $field 要获取的字段名
 * @return string         分类信息
 */
function get_category($id, $field = null){
    static $list;

    /* 非法分类ID */
    if(empty($id) || !is_numeric($id)){
        return '';
    }

    /* 读取缓存数据 */
    if(empty($list)){
        $list = S('sys_category_list');
    }

    /* 获取分类名称 */
    if(!isset($list[$id])){
        $cate = M('Category')->find($id);
        if(!$cate || 1 != $cate['status']){ //不存在分类，或分类被禁用
            return '';
        }
        $list[$id] = $cate;
        S('sys_category_list', $list); //更新缓存
    }
    return is_null($field) ? $list[$id] : $list[$id][$field];
}

/* 根据ID获取分类标识 */
function get_category_name($id){
    return get_category($id, 'name');
}

/* 根据ID获取分类名称 */
function get_category_title($id){
    return get_category($id, 'title');
}

/**
 * 获取顶级模型信息
 */
function get_top_model($model_id=null){
    $map   = array('status' => 1, 'extend' => 0);
    if(!is_null($model_id)){
        $map['id']  =   array('neq',$model_id);
    }
    $model = M('Model')->where($map)->field(true)->select();
    foreach ($model as $value) {
        $list[$value['id']] = $value;
    }
    return $list;
}

/**
 * 获取文档模型信息
 * @param  integer $id    模型ID
 * @param  string  $field 模型字段
 * @return array
 */
function get_document_model($id = null, $field = null){
    static $list;

    /* 非法分类ID */
    if(!(is_numeric($id) || is_null($id))){
        return '';
    }

    /* 读取缓存数据 */
    if(empty($list)){
        $list = S('DOCUMENT_MODEL_LIST');
    }

    /* 获取模型名称 */
    if(empty($list)){
        $map   = array('status' => 1, 'extend' => 1);
        $model = M('Model')->where($map)->field(true)->select();
        foreach ($model as $value) {
            $list[$value['id']] = $value;
        }
        S('DOCUMENT_MODEL_LIST', $list); //更新缓存
    }

    /* 根据条件返回数据 */
    if(is_null($id)){
        return $list;
    } elseif(is_null($field)){
        return $list[$id];
    } else {
        return $list[$id][$field];
    }
}

/**
 * 解析UBB数据
 * @param string $data UBB字符串
 * @return string 解析为HTML的数据
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function ubb($data){
    //TODO: 待完善，目前返回原始数据
    return $data;
}

/**
 * 记录行为日志，并执行该行为的规则
 * @param string $action 行为标识
 * @param string $model 触发行为的模型名
 * @param int $record_id 触发行为的记录id
 * @param int $user_id 执行行为的用户id
 * @return boolean
 * @author huajie <banhuajie@163.com>
 */
function action_log($action = null, $model = null, $record_id = null, $user_id = null){

    //参数检查
    if(empty($action) || empty($model) || empty($record_id)){
        return '参数不能为空';
    }
    if(empty($user_id)){
        $user_id = is_login();
    }

    //查询行为,判断是否执行
    $action_info = M('Action')->getByName($action);
    if($action_info['status'] != 1){
        return '该行为被禁用或删除';
    }

    //插入行为日志
    $data['action_id']      =   $action_info['id'];
    $data['user_id']        =   $user_id;
    $data['action_ip']      =   ip2long(get_client_ip());
    $data['model']          =   $model;
    $data['record_id']      =   $record_id;
    $data['create_time']    =   NOW_TIME;

    //解析日志规则,生成日志备注
    if(!empty($action_info['log'])){
        if(preg_match_all('/\[(\S+?)\]/', $action_info['log'], $match)){
            $log['user']    =   $user_id;
            $log['record']  =   $record_id;
            $log['model']   =   $model;
            $log['time']    =   NOW_TIME;
            $log['data']    =   array('user'=>$user_id,'model'=>$model,'record'=>$record_id,'time'=>NOW_TIME);
            foreach ($match[1] as $value){
                $param = explode('|', $value);
                if(isset($param[1])){
                    $replace[] = call_user_func($param[1],$log[$param[0]]);
                }else{
                    $replace[] = $log[$param[0]];
                }
            }
            $data['remark'] =   str_replace($match[0], $replace, $action_info['log']);
        }else{
            $data['remark'] =   $action_info['log'];
        }
    }else{
        //未定义日志规则，记录操作url
        $data['remark']     =   '操作url：'.$_SERVER['REQUEST_URI'];
    }

    M('ActionLog')->add($data);

    if(!empty($action_info['rule'])){
        //解析行为
        $rules = parse_action($action, $user_id);

        //执行行为
        $res = execute_action($rules, $action_info['id'], $user_id);
    }
}

/**
 * 解析行为规则
 * 规则定义  table:$table|field:$field|condition:$condition|rule:$rule[|cycle:$cycle|max:$max][;......]
 * 规则字段解释：table->要操作的数据表，不需要加表前缀；
 *              field->要操作的字段；
 *              condition->操作的条件，目前支持字符串，默认变量{$self}为执行行为的用户
 *              rule->对字段进行的具体操作，目前支持四则混合运算，如：1+score*2/2-3
 *              cycle->执行周期，单位（小时），表示$cycle小时内最多执行$max次
 *              max->单个周期内的最大执行次数（$cycle和$max必须同时定义，否则无效）
 * 单个行为后可加 ； 连接其他规则
 * @param string $action 行为id或者name
 * @param int $self 替换规则里的变量为执行用户的id
 * @return boolean|array: false解析出错 ， 成功返回规则数组
 * @author huajie <banhuajie@163.com>
 */
function parse_action($action = null, $self){
    if(empty($action)){
        return false;
    }

    //参数支持id或者name
    if(is_numeric($action)){
        $map = array('id'=>$action);
    }else{
        $map = array('name'=>$action);
    }

    //查询行为信息
    $info = M('Action')->where($map)->find();
    if(!$info || $info['status'] != 1){
        return false;
    }

    //解析规则:table:$table|field:$field|condition:$condition|rule:$rule[|cycle:$cycle|max:$max][;......]
    $rules = $info['rule'];
    $rules = str_replace('{$self}', $self, $rules);
    $rules = explode(';', $rules);
    $return = array();
    foreach ($rules as $key=>&$rule){
        $rule = explode('|', $rule);
        foreach ($rule as $k=>$fields){
            $field = empty($fields) ? array() : explode(':', $fields);
            if(!empty($field)){
                $return[$key][$field[0]] = $field[1];
            }
        }
        //cycle(检查周期)和max(周期内最大执行次数)必须同时存在，否则去掉这两个条件
        if(!array_key_exists('cycle', $return[$key]) || !array_key_exists('max', $return[$key])){
            unset($return[$key]['cycle'],$return[$key]['max']);
        }
    }

    return $return;
}

/**
 * 执行行为
 * @param array $rules 解析后的规则数组
 * @param int $action_id 行为id
 * @param array $user_id 执行的用户id
 * @return boolean false 失败 ， true 成功
 * @author huajie <banhuajie@163.com>
 */
function execute_action($rules = false, $action_id = null, $user_id = null){
    if(!$rules || empty($action_id) || empty($user_id)){
        return false;
    }

    $return = true;
    foreach ($rules as $rule){

        //检查执行周期
        $map = array('action_id'=>$action_id, 'user_id'=>$user_id);
        $map['create_time'] = array('gt', NOW_TIME - intval($rule['cycle']) * 3600);
        $exec_count = M('ActionLog')->where($map)->count();
        if($exec_count > $rule['max']){
            continue;
        }

        //执行数据库操作
        $Model = M(ucfirst($rule['table']));
        $field = $rule['field'];
        $res = $Model->where($rule['condition'])->setField($field, array('exp', $rule['rule']));

        if(!$res){
            $return = false;
        }
    }
    return $return;
}

//基于数组创建目录和文件
function create_dir_or_files($files){
    foreach ($files as $key => $value) {
        if(substr($value, -1) == '/'){
            mkdir($value);
        }else{
            @file_put_contents($value, '');
        }
    }
}

if(!function_exists('array_column')){
    function array_column(array $input, $columnKey, $indexKey = null) {
        $result = array();
        if (null === $indexKey) {
            if (null === $columnKey) {
                $result = array_values($input);
            } else {
                foreach ($input as $row) {
                    $result[] = $row[$columnKey];
                }
            }
        } else {
            if (null === $columnKey) {
                foreach ($input as $row) {
                    $result[$row[$indexKey]] = $row;
                }
            } else {
                foreach ($input as $row) {
                    $result[$row[$indexKey]] = $row[$columnKey];
                }
            }
        }
        return $result;
    }
}

/**
 * 获取表名（不含表前缀）
 * @param string $model_id
 * @return string 表名
 * @author huajie <banhuajie@163.com>
 */
function get_table_name($model_id = null){
    if(empty($model_id)){
        return false;
    }
    $Model = M('Model');
    $name = '';
    $info = $Model->getById($model_id);
    if($info['extend'] != 0){
        $name = $Model->getFieldById($info['extend'], 'name').'_';
    }
    $name .= $info['name'];
    return $name;
}

/**
 * 获取属性信息并缓存
 * @param  integer $id    属性ID
 * @param  string  $field 要获取的字段名
 * @return string         属性信息
 */
function get_model_attribute($model_id, $group = true,$fields=true){
    static $list;

    /* 非法ID */
    if(empty($model_id) || !is_numeric($model_id)){
        return '';
    }

    /* 获取属性 */
    if(!isset($list[$model_id])){
        $map = array('model_id'=>$model_id);
        $extend = M('Model')->getFieldById($model_id,'extend');

        if($extend){
            $map = array('model_id'=> array("in", array($model_id, $extend)));
        }
        $info = M('Attribute')->where($map)->field($fields)->select();
        $list[$model_id] = $info;
    }

    $attr = array();
    if($group){
        foreach ($list[$model_id] as $value) {
            $attr[$value['id']] = $value;
        }
        $model     = M("Model")->field("field_sort,attribute_list,attribute_alias")->find($model_id);
        $attribute = explode(",", $model['attribute_list']);
        if (empty($model['field_sort'])) { //未排序
            $group = array(1 => array_merge($attr));
        } else {
            $group = json_decode($model['field_sort'], true);

            $keys = array_keys($group);
            foreach ($group as &$value) {
                foreach ($value as $key => $val) {
                    $value[$key] = $attr[$val];
                    unset($attr[$val]);
                }
            }

            if (!empty($attr)) {
                foreach ($attr as $key => $val) {
                    if (!in_array($val['id'], $attribute)) {
                        unset($attr[$key]);
                    }
                }
                $group[$keys[0]] = array_merge($group[$keys[0]], $attr);
            }
        }
        if (!empty($model['attribute_alias'])) {
            $alias  = preg_split('/[;\r\n]+/s', $model['attribute_alias']);
            $fields = array();
            foreach ($alias as &$value) {
                $val             = explode(':', $value);
                $fields[$val[0]] = $val[1];
            }
            foreach ($group as &$value) {
                foreach ($value as $key => $val) {
                    if (!empty($fields[$val['name']])) {
                        $value[$key]['title'] = $fields[$val['name']];
                    }
                }
            }
        }
        $attr = $group;
    }else{
        foreach ($list[$model_id] as $value) {
            $attr[$value['name']] = $value;
        }
    }
    return $attr;
}

/**
 * 调用系统的API接口方法（静态方法）
 * api('User/getName','id=5'); 调用公共模块的User接口的getName方法
 * api('Admin/User/getName','id=5');  调用Admin模块的User接口
 * @param  string  $name 格式 [模块名]/接口名/方法名
 * @param  array|string  $vars 参数
 */
function api($name,$vars=array()){
    $array     = explode('/',$name);
    $method    = array_pop($array);
    $classname = array_pop($array);
    $module    = $array? array_pop($array) : 'Common';
    $callback  = $module.'\\Api\\'.$classname.'Api::'.$method;
    if(is_string($vars)) {
        parse_str($vars,$vars);
    }
    return call_user_func_array($callback,$vars);
}

/**
 * 根据条件字段获取指定表的数据
 * @param mixed $value 条件，可用常量或者数组
 * @param string $condition 条件字段
 * @param string $field 需要返回的字段，不传则返回整个数据
 * @param string $table 需要查询的表
 * @author huajie <banhuajie@163.com>
 */
function get_table_field($value = null, $condition = 'id', $field = null, $table = null){
    if(empty($value) || empty($table)){
        return false;
    }

    //拼接参数
    $map[$condition] = $value;
    $info = M(ucfirst($table))->where($map);
    if(empty($field)){
        $info = $info->field(true)->find();
    }else{
        $info = $info->getField($field);
    }
    return $info;
}

/**
 * 获取链接信息
 * @param int $link_id
 * @param string $field
 * @return 完整的链接信息或者某一字段
 * @author huajie <banhuajie@163.com>
 */
function get_link($link_id = null, $field = 'url'){
    $link = '';
    if(empty($link_id)){
        return $link;
    }
    $link = M('Url')->getById($link_id);
    if(empty($field)){
        return $link;
    }else{
        return $link[$field];
    }
}

/**
 * 获取文档封面图片
 * @param int $cover_id
 * @param string $field
 * @return 完整的数据  或者  指定的$field字段值
 * @author huajie <banhuajie@163.com>
 */
function get_cover($cover_id, $field = null){
    if(empty($cover_id)){
        return false;
    }
    $picture = M('Picture')->where(array('status'=>1))->getById($cover_id);
    if($field == 'path'){
        if(!empty($picture['url'])){
            $picture['path'] = $picture['url'];
        }else{
            $picture['path'] = __ROOT__.$picture['path'];
        }
    }
    return empty($field) ? $picture : $picture[$field];
}

/**
 * 检查$pos(推荐位的值)是否包含指定推荐位$contain
 * @param number $pos 推荐位的值
 * @param number $contain 指定推荐位
 * @return boolean true 包含 ， false 不包含
 * @author huajie <banhuajie@163.com>
 */
function check_document_position($pos = 0, $contain = 0){
    if(empty($pos) || empty($contain)){
        return false;
    }

    //将两个参数进行按位与运算，不为0则表示$contain属于$pos
    $res = $pos & $contain;
    if($res !== 0){
        return true;
    }else{
        return false;
    }
}

/**
 * 获取数据的所有子孙数据的id值
 * @author 朱亚杰 <xcoolcc@gmail.com>
 */

function get_stemma($pids,Model &$model, $field='id'){
    $collection = array();

    //非空判断
    if(empty($pids)){
        return $collection;
    }

    if( is_array($pids) ){
        $pids = trim(implode(',',$pids),',');
    }
    $result     = $model->field($field)->where(array('pid'=>array('IN',(string)$pids)))->select();
    $child_ids  = array_column ((array)$result,'id');

    while( !empty($child_ids) ){
        $collection = array_merge($collection,$result);
        $result     = $model->field($field)->where( array( 'pid'=>array( 'IN', $child_ids ) ) )->select();
        $child_ids  = array_column((array)$result,'id');
    }
    return $collection;
}

/**
 * 验证分类是否允许发布内容
 * @param  integer $id 分类ID
 * @return boolean     true-允许发布内容，false-不允许发布内容
 */
function check_category($id){
    if (is_array($id)) {
        $id['type']	=	!empty($id['type'])?$id['type']:2;
        $type = get_category($id['category_id'], 'type');
        $type = explode(",", $type);
        return in_array($id['type'], $type);
    } else {
        $publish = get_category($id, 'allow_publish');
        return $publish ? true : false;
    }
}

/**
 * 检测分类是否绑定了指定模型
 * @param  array $info 模型ID和分类ID数组
 * @return boolean     true-绑定了模型，false-未绑定模型
 */
function check_category_model($info){
    $cate   =   get_category($info['category_id']);
    $array  =   explode(',', $info['pid'] ? $cate['model_sub'] : $cate['model']);
    return in_array($info['model_id'], $array);
}


function  show($status, $message,$data=array(),$n,$num) {
    if($data){
        if($n && $num){
            $reuslt = array(
                'code' => $status,
                'msg' => $message,
                'data' => $data,
                'n' => $n,
                'num' => $num,
            );
        }
        if(!$n && !$num){
            $reuslt = array(
                'code' => $status,
                'msg' => $message,
                'data' => $data,
            );
        }
    }else{
        $reuslt = array(
            'code' => 1,
            'msg' => $message,
            'data'=>array()
        );
    }

    exit(json_encode($reuslt));
}


function  show1($status, $message) {
    $reuslt = array(
        'code' => $status,
        'msg' => $message,

    );
    exit(json_encode($reuslt));
}


//根据地区id获取地区名
function getarea($id){
    if($id){
        $name=M('district')->where('id='.$id)->getField('name');
        if($name){
            return $name;
        }else{
            return '';
        }
    }else{
        return '';
    }
}

function getusername($id){
    if($id){
        $name=M('User')->where('id='.$id)->getField('nickname');
        if($name){
            return $name;
        }else{
            return '';
        }
    }else{
        return '';
    }
}


//根据图片id获取图片路径
function getImgurl($imgid){
    if($imgid){
        $where['id']=$imgid;
        $url=M('Picture')->where($where)->getField('path');
        if($url){
            return 'http://'.$_SERVER['HTTP_HOST'].$url;
        }else{
            return '';
        }
    }
}

function jiequ($str){
    $res=strpos($str,'http://');
    //首先检测是否有'http://'
    $str1='http://';
    $len=strlen($str1)+1;
    //存在就从这里开始找'/',获取后面的内容
    $pos=strpos($str,'/',($res+$len));
    $newstr=substr($str,$pos);
    return $newstr;
}


function rz_status($n){
    if($n==1){
        $str="审核中";
    }else if($n==3){
        $str="审核通过";
    }else if($n==2){
        $str="审核不通过";
    }else{
        $str="未认证";
    }

    return $str;
}


//生成订单号
function setOrderSn() {
    list($t1,$t2)=explode(' ',microtime());
    $t3=explode('.',$t1*10000);
    return $t2.$t3[0].(rand(10000,99999));
}


//使用curl 发送get/post请求 $fileds存在就是post请求
function curl($url,$fileds){
    $ch = curl_init();
    //设置我们请求的地址
    curl_setopt($ch, CURLOPT_URL, $url);
    //数据返回不要直接显示
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    //禁止证书验证
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
    if ($fileds) {
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $fileds);
    }

    $data='';
    if (curl_exec($ch)) {
        //如果发送成功,获取数据
        $data=curl_multi_getcontent($ch);
    }
    curl_close($ch);
    return $data;
}

function isint($value)
{
    if (is_numeric($value) && is_int($value + 0) && ($value + 0) > 0) {
        return true;
    }
    return false;
}


/**
 * 等级计算
 * @param int $exp  经验值
 * 等级计算规则：$exp = $rank*100+($rank-1)*100
 * */
function exp_rank($exp){
    if($exp == 0){
        return 1;
    }else{
        $exp_up = C('EXP_UP');
        $rank = ceil(($exp+200)/300);
        return $rank;
    }
}

/**
 * 生成随机数
 * @param $uid 用户id
 *        $all_len 随机数总长度
 * */
function rand_num($uid,$all_len){
    $rand_after = rand(100,999);

    $len = $all_len-strlen($rand_after)-strlen($uid);
    $rand_later = '';
    for($i = 0; $i < $len; $i++){
        $rand_later .= mt_rand(0, 9);
    }

    $rand_num = $rand_after.$uid.$rand_later;
    return $rand_num;
}

/************************直播方法封装****************************/

/**
 * 获取推流地址
 * 如果不传key和过期时间，将返回不含防盗链的url5
 * @param bizId 您在腾讯云分配到的bizid
 *        streamId 您用来区别不同推流地址的唯一id
 *        key 安全密钥
 *        time 过期时间 sample 2016-11-12 12:00:00
 * @return String url */
function getPushUrl($streamId, $time = null){
    $bizId = C('ZB_BIZID');
    $key = C('PUSH_KEY');

    if($bizId != '27240') return 'bizId有误，请前往腾讯云查看：https://console.cloud.tencent.com/live/livecodemanagde';
    if($key != '5b494775a320c8f7e46e8261b17f3ed2') return '推流防盗链key有误，请前往腾讯云查看：https://console.cloud.tencent.com/live/livecodemanagde';

    if($key && $time){
        $txTime = strtoupper(base_convert(strtotime($time),10,16));

        $livecode = $bizId."_".$streamId; //直播码
        $txSecret = md5($key.$livecode.$txTime);
        $ext_str = "?".http_build_query(array(
                                            "bizid"=> $bizId,
                                            "txSecret"=> $txSecret,
                                            "txTime"=> $txTime
                                        ));
    }
    return "rtmp://".$bizId.".livepush.myqcloud.com/live/".$livecode.(isset($ext_str)?$ext_str:"");
}

/**
 * 获取拉流地址
 * 如果不传key和过期时间，将返回不含防盗链的url
 * @param bizId 您在腾讯云分配到的bizid
 *        streamId 您用来区别不同推流地址的唯一id
 *        key 安全密钥
 *        time 过期时间 sample 2016-11-12 12:00:00
 * @return String url */
function lm_getPlayUrl($streamId, $time = null){
    $bizId = C('ZB_BIZID');
    $key = C('PUSH_KEY');

    if($bizId != '27240') return 'bizId有误，请前往腾讯云查看：https://console.cloud.tencent.com/live/livecodemanagde';
    if($key != '5b494775a320c8f7e46e8261b17f3ed2') return '推流防盗链key有误，请前往腾讯云查看：https://console.cloud.tencent.com/live/livecodemanagde';

    if($key && $time){
        $txTime = strtoupper(base_convert(strtotime($time),10,16));

        $livecode = $bizId."_".$streamId; //直播码
        $txSecret = md5($key.$livecode.$txTime);
        $ext_str = "?".http_build_query(array(
                                            "bizid"=> $bizId,
                                            "txSecret"=> $txSecret,
                                            "txTime"=> $txTime
                                        ));
    }
    return "rtmp://".$bizId.".liveplay.myqcloud.com/live/".$livecode.(isset($ext_str)?$ext_str:"");
}

/**
 * 获取播放地址
 * @param bizId 您在腾讯云分配到的bizid
 *        streamId 您用来区别不同推流地址的唯一id
 * @return String url */
function getPlayUrl($streamId){
    $bizId = C('ZB_BIZID');

    if($bizId != '27240') return 'bizId有误，请前往腾讯云查看：https://console.cloud.tencent.com/live/livecodemanagde';

    $livecode = $bizId."_".$streamId; //直播码
    return array(
        "rtmp://".$bizId.".liveplay.myqcloud.com/live/".$livecode,
        "http://".$bizId.".liveplay.myqcloud.com/live/".$livecode.".flv",
        "http://".$bizId.".liveplay.myqcloud.com/live/".$livecode.".m3u8"
    );
}

/**
 * 获取播放地址
 * @param bizId 您在腾讯云分配到的bizid
 *        streamId 您用来区别不同推流地址的唯一id
 * @return String url */
function flv_getPlayUrl($streamId){
    $bizId = C('ZB_BIZID');

    if($bizId != '27240') return 'bizId有误，请前往腾讯云查看：https://console.cloud.tencent.com/live/livecodemanagde';

    $livecode = $bizId."_".$streamId; //直播码
    return "http://".$bizId.".liveplay.myqcloud.com/live/".$livecode.".flv";
}


/**
 * 查询统计信息
 *
 * Get_LiveStat：查询指定直播流的推流和播放信息；
 * Get_LivePushStat：仅返回推流统计信息以提高查询效率；
 * Get_LivePlayStat：仅返回播放统计信息以提高查询效率；
 *
 * 用途
 * 查询某条直播流的统计信息（如观看人数、带宽、码率、帧率等）；
 * 查询当前正在直播状态中的若干条直播流的统计信息（建议采用分页查询避免单次回包数据过大）。
 *
 * @param interface 接口名（ Get_LiveStat || Get_LivePushStat || Get_LivePlayStat ）
 *        page 分页页码
 *        page_size 分页大小
 *        stream_id 不设置 stream_id：查询所有正在直播中的流
 *        pull_domain 播放域名，如果不填则返回所有域名的播放数据
 * */
function get_live_info($interface,$page = 1,$page_size = 10,$stream_id = '',$pull_domain = ''){
    if($interface != 'Get_LiveStat' && $interface != 'Get_LivePushStat' && $interface != 'Get_LivePlayStat') return '接口名必填，且只能传入Get_LiveStat || Get_LivePushStat || Get_LivePlayStat，接口文档：https://cloud.tencent.com/document/api/267/6110';
    $t = time();
    $key = C('ZB_KEY');
    $sign = md5($key.$t);
    $appid = C('ZB_APPID');

    if($key != '565c1ac6056e7cbc4f533632f70940cb') return 'API鉴权key有误，请前往腾讯云查看：https://console.cloud.tencent.com/live/livecodemanagde';
    if($appid != '1256405867') return 'appid有误，请前往腾讯云查看：https://console.cloud.tencent.com/live/livecodemanagde';

    $url = 'http://statcgi.video.qcloud.com/common_access?cmd='.$appid.'&interface='.$interface.'&Param.n.page_no='.$page.'&Param.n.page_size='.$page_size.'&t='.$t.'&sign='.$sign;

    if($stream_id) $url = $url.'&Param.s.stream_id='.$stream_id;

    if($pull_domain) $url = $url.'&Param.s.pull_domain='.$pull_domain;

    return file_get_contents($url);
}

/**
 * 获取推流历史信息
 *
 * Get_LivePushStatHistory：获取推流历史信息;
 *
 * 可获取指定时间段内推流信息；
 * 推流信息的统计数据每 5 秒钟更新一次。
 * 使用该接口需要后台配置，如需调用该接口，请联系腾讯商务人员或者 提交工单(https://console.cloud.tencent.com/workorder/category)，联系电话：4009-100-100。
 *
 * @param start_time 查询起始时间
 *        end_time 查询结束时间
 *        stream_id 流ID
 * */
function get_live_push_history($start_time,$end_time,$stream_id){
    $key = C('ZB_KEY');
    $appid = C('ZB_APPID');
    $t = time();
    $sign = md5($key.$t);
    $bizId = C('ZB_BIZID');

    if($bizId != '27240') return 'bizId有误，请前往腾讯云查看：https://console.cloud.tencent.com/live/livecodemanagde';
    if($key != '565c1ac6056e7cbc4f533632f70940cb') return 'API鉴权key有误，请前往腾讯云查看：https://console.cloud.tencent.com/live/livecodemanagde';
    if($appid != '1256405867') return 'appid有误，请前往腾讯云查看：https://console.cloud.tencent.com/live/livecodemanagde';
    if(empty($start_time)) return '开始时间不能为空';
    if(empty($end_time)) return '结束时间不能为空';
    if(empty($stream_id)) return '流ID不能为空';

    $url = 'http://statcgi.video.qcloud.com/common_access?cmd='.$appid.'&interface=Get_LivePushStatHistory&Param.n.start_time='.$start_time.'&Param.n.end_time='.$end_time.'&Param.s.stream_id='.$bizId.'_'.$stream_id.'&t='.$t.'&sign='.$sign;

    return file_get_contents($url);
}

/**
 * 获取播放统计历史信息
 *
 * Get_LivePlayStatHistory：获取播放统计历史信息;
 *
 * 可获取指定时间段内播放信息。
 * 播放信息的统计数据每 1 分钟更新一次。
 * 该接口支持直播码模式，同时也支持频道模式。
 * 使用该接口需要后台配置，如需调用该接口，请联系腾讯商务人员或者 提交工单(https://console.cloud.tencent.com/workorder/category)，联系电话：4009-100-100。
 *
 * @param start_time 查询起始时间
 *        end_time 查询结束时间
 *        stream_id 流ID   不填就是获取总带宽
 *        domain 域名   若不填，取这个 APPID 下的总数据，需要填写 cname 前的原始播放域名
 * */
function get_live_play_history($start_time,$end_time,$stream_id = '',$domain = ''){
    $key = C('ZB_KEY');
    $appid = C('ZB_APPID');
    $t = time();
    $sign = md5($key.$t);

    if($key != '565c1ac6056e7cbc4f533632f70940cb') return 'API鉴权key有误，请前往腾讯云查看：https://console.cloud.tencent.com/live/livecodemanagde';
    if($appid != '1256405867') return 'appid有误，请前往腾讯云查看：https://console.cloud.tencent.com/live/livecodemanagde';
    if(empty($start_time)) return '开始时间不能为空';
    if(empty($end_time)) return '结束时间不能为空';

    $url = 'http://statcgi.video.qcloud.com/common_access?cmd='.$appid.'&interface=Get_LivePlayStatHistory&Param.n.start_time='.$start_time.'&Param.n.end_time='.$end_time.'t='.$t.'&sign='.$sign;

    if($stream_id) $url = $url.'&Param.s.stream_id='.$stream_id;
    if($domain) $url = $url.'&Param.s.domain='.$domain;

    return file_get_contents($url);
}

/**
 * 开启关闭推流
 *
 * 对一条直播流执行禁用、断流和允许推流操作
 * 【禁用】 表示不能再继续使用该流 ID 推流；如果正在推流，则推流会被中断，中断后不可再次推流
 * 【断流】 表示中断正在推的流，断流后可以再次推流
 * 【允许推流】 表示启用该流 ID，允许用该流 ID 推流
 *
 * Live_Channel_SetStatus：开启关闭推流;
 *
 * 一条直播流一旦被设置为【禁用】状态，推流链路将被腾讯云主动断开，并且后续的推流请求也会被拒绝，一条流最长禁用 3 个月，超过 3 个月，禁用失效。
 *
 * @param room_id 主播房间号
 *        status 开关状态 	0 表示禁用，1 表示允许推流，2 表示断流
 * */
function live_channel_setStatus($room_id,$status){
    $bizId = C('ZB_BIZID');
    $key = C('ZB_KEY');
    $appid = C('ZB_APPID');

    $t = time();
    $sign = md5($key.$t);

    if($bizId != '27240') return 'bizId有误，请前往腾讯云查看：https://console.cloud.tencent.com/live/livecodemanagde';
    if($key != '565c1ac6056e7cbc4f533632f70940cb') return 'API鉴权key有误，请前往腾讯云查看：https://console.cloud.tencent.com/live/livecodemanagde';
    if($appid != '1256405867') return 'appid有误，请前往腾讯云查看：https://console.cloud.tencent.com/live/livecodemanagde';
    if($status != 0 || $status != 1 || $status != 2) return '推流状态有误';
    if(empty($room_id)) return '主播房间号不能为空';

    $channel_id = $bizId.'_'.$room_id;

    $url = 'http://fcgi.video.qcloud.com/common_access?appid='.$appid.'&interface=Live_Channel_SetStatus&Param.s.channel_id='.$channel_id.'&Param.n.status='.$status.'&t='.$t.'&sign='.$sign;

    return file_get_contents($url);
}

/**
 * 查询直播中频道列表
 *
 * Live_Channel_GetLiveChannelList：查询频道列表;
 * */
function search_live_channe_list(){
    $key = C('ZB_KEY');
    $appid = C('ZB_APPID');

    $t = time();
    $sign = md5($key.$t);

    if($key != '565c1ac6056e7cbc4f533632f70940cb') return 'API鉴权key有误，请前往腾讯云查看：https://console.cloud.tencent.com/live/livecodemanagde';
    if($appid != '1256405867') return 'appid有误，请前往腾讯云查看：https://console.cloud.tencent.com/live/livecodemanagde';

    $url = 'http://fcgi.video.qcloud.com/common_access?appid='.$appid.'&interface=Live_Channel_GetChannelList&t='.$t.'&sign='.$sign;

    return file_get_contents($url);
}

/**
 * 暂停并延迟恢复
 *
 * 调用该接口可以暂停推某路流（即禁止推流），如果要恢复主播推流，可再次调用该接口或者设置一个恢复时间，到达指定时间后允许推流，最长禁止推流 3 个月
 * 即禁止推流截止时间最长为当前时间往后 3 个月，如果超过 3 个月，则以 3 个月为准。
 *
 * channel_manager：暂停推流并延迟恢复接口;
 *
 * 一条直播流一旦被设置为【禁用】状态，推流链路将被腾讯云主动断开，并且后续的推流请求也会被拒绝，一条流最长禁用 3 个月，超过 3 个月，禁用失效。
 *
 * @param room_id 主播房间号
 *        abstime_end 禁播截止的时间戳   禁播截止的绝对时间，请填写UNIX 时间戳（十进制），系统最多禁播三个月
 *        action 动作   断流：forbid；恢复推流：resume
 * */
function channel_manager($room_id,$abstime_end,$action){
    $key = C('ZB_KEY');
    $appid = C('ZB_APPID');
    $bizId = C('ZB_BIZID');

    $t = time();
    $sign = md5($key.$t);

    if($bizId != '27240') return 'bizId有误，请前往腾讯云查看：https://console.cloud.tencent.com/live/livecodemanagde';
    if($key != '565c1ac6056e7cbc4f533632f70940cb') return 'API鉴权key有误，请前往腾讯云查看：https://console.cloud.tencent.com/live/livecodemanagde';
    if($appid != '1256405867') return 'appid有误，请前往腾讯云查看：https://console.cloud.tencent.com/live/livecodemanagde';
    if(empty($room_id)) return '主播房间号不能为空';
    if($abstime_end) return '禁播截止的时间戳不能为空';
    if($action) return '操作动作不能为空';

    $channel_id = $bizId.'_'.$room_id;
    $url = 'URL = http://fcgi.video.qcloud.com/common_access?appid='.$appid.'&interface=channel_manager&Param.s.channel_id='.$channel_id.'&Param.n.abstime_end='.$abstime_end.'&t='.$t.'&sign='.$sign.'&Param.s.action='.$action;

    return file_get_contents($url);
}


/**
 * 查询直播状态
 * @param  $channel_id  biz_id_房间号：27240_7779692403
 * */
function singer_channel($channel_id){
    $key = C('ZB_KEY');
    $appid = C('ZB_APPID');

    $t = time();
    $sign = md5($key.$t);

    if(empty($channel_id)) return '主播房间号不能为空';
    $url="http://fcgi.video.qcloud.com/common_access?appid=$appid&interface=Live_Channel_GetStatus&Param.s.channel_id=$channel_id&t=$t&sign=$sign";
    return file_get_contents($url);

}


/************************直播方法封装****************************/


function xzb_curl_send($api,$param){
    $header=array(
        "Accept: application/json",
        "Content-Type: application/json;charset=utf-8",
    );

    $url = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].'/'.$api;
    //初始化
    $curl = curl_init();
    //设置抓取的url
    curl_setopt($curl, CURLOPT_URL, $url);
    //设置头文件的信息作为数据流输出
    curl_setopt($curl, CURLOPT_HEADER, 0);
    //设置获取的信息以文件流的形式返回，而不是直接输出。
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 0);

    curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
    curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($param));

    //执行命令
    $data = curl_exec($curl);
    //关闭URL请求
    curl_close($curl);

    return $data;
}

function send_curl($url,$param){
    $header=array(
        "Accept: application/json",
        "Content-Type: application/json;charset=utf-8",
    );

    //初始化
    $curl = curl_init();
    //设置抓取的url
    curl_setopt($curl, CURLOPT_URL, $url);
    //设置头文件的信息作为数据流输出
    curl_setopt($curl, CURLOPT_HEADER, 0);
    //设置获取的信息以文件流的形式返回，而不是直接输出。
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 0);

    curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
    curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($param));

    //执行命令
    $data = curl_exec($curl);
    //关闭URL请求
    curl_close($curl);

    return $data;
}


/**
 * 调用腾讯云接口获取直播列表
 * @param userid 小直播userid
 *        token sdk生成token字符串
 * */
function zb_list($userid,$token){
    $n = 0;
    $num = 200;

    $header=array(
        "Accept: application/json",
        "Content-Type: application/json;charset=utf-8",
    );

    $url = 'https://room.qcloud.com/weapp/live_room/get_room_list?userID='.$userid.'&token='.$token;

    $param = [
        'cnt' => $num,
        'index' => $n
    ];

    //初始化
    $curl = curl_init();
    //设置抓取的url
    curl_setopt($curl, CURLOPT_URL, $url);
    //设置头文件的信息作为数据流输出
    curl_setopt($curl, CURLOPT_HEADER, 0);
    //设置获取的信息以文件流的形式返回，而不是直接输出。
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // 信任任何证书
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1); // 检查证书中是否设置域名（为0也可以，就是连域名存在与否都不验证了）

    curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
    curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($param));

    //执行命令
    $data = curl_exec($curl);
    //关闭URL请求
    curl_close($curl);

    return json_decode($data,true);
}

/**
 * 云通信
 * 生成userSig
 * @param $room_id 即为user表中的number
 * */
function get_UserSig($room_id,$type = false){
    vendor('userSig.WebRTCSigApi');
    /* demo */
    try{
        $sdkappid = C('YUN_SDKAPPID');  //腾讯云云通信sdkappid
        $roomid = $room_id;          //音视频房间号roomid
        $userid = C('YUN_USERID');    //用户名userid

        $api = new \WebRTCSigApi();

        //设置在腾讯云申请的sdkappid
        $api->setSdkAppid($sdkappid);

        //读取私钥的内容
        //PS:不要把私钥文件暴露到外网直接下载了哦
        $private = file_get_contents('./public/key/private_key');

        //设置私钥(签发usersig需要用到）
        $api->SetPrivateKey($private);

        //读取公钥的内容
        $public = file_get_contents('./public/key/public_key');

        //设置公钥(校验userSig和privMapEncrypt需要用到，校验只是为了验证，实际业务中不需要校验）
        $api->SetPublicKey($public);

        //生成privMapEncrypt
        $privMapEncrypt = $api->genPrivMapEncrypt($userid, $roomid);

        //生成userSig
        if($type == true){
            //禁言生成签名
            $userSig = $api->genUserSig($userid,24*60*60*180);//默认一天过期
        }else{
            //登录生成签名
            $userSig = $api->genUserSig($roomid,24*60*60*180);//默认一天过期
        }
        //校验
        $result = $api->verifyUserSig($userSig, $userid, $init_time, $expire_time, $error_msg);
        $result = $api->verifyPrivMapEncrypt($privMapEncrypt, $userid, $init_time, $expire_time, $userbuf, $error_msg);
        //打印结果
        $ret =  array(
            'privMapEncrypt' => $privMapEncrypt,
            'userSig' => $userSig
        );
        return $ret['userSig'];
    }catch(Exception $e){
        echo $e->getMessage();
    }
}
/**************云通信消息推送封装**************/
/**
 * 设置应用属性名称
 * */
function im_set_attr_name(){
    $url = 'https://console.tim.qq.com/v4/openim/im_set_attr_name?usersig='.get_UserSig(C('YUN_USERID')).'&identifier='.C('YUN_USERID').'&sdkappid='.C('YUN_SDKAPPID').'&random='.rand(100000,999999).'&contenttype=json';
    $set_json = '{
        "AttrNames": {
            "0": "uid",
            "1": "vip",
            "2": "age"
        }
    }';
    $json = curl($url,$set_json);
    return $json;
}
/**
 * 获取应用属性名称
 * */
function im_get_attr_name(){
    $array = [];
    $url = 'https://console.tim.qq.com/v4/openim/im_get_attr_name?usersig='.get_UserSig(C('YUN_USERID')).'&identifier='.C('YUN_USERID').'&sdkappid='.C('YUN_SDKAPPID').'&random='.rand(100000,999999).'&contenttype=json';
    $set_json = '{
            "AttrNames": '.json_encode($array).'
        }';
    $json = curl($url,$set_json);
    return $json;
}
/**
 * 设置用户uid属性
 * */
function im_set_attr($number,$uid){
    $url = 'https://console.tim.qq.com/v4/openim/im_set_attr?usersig='.get_UserSig(C('YUN_USERID')).'&identifier='.C('YUN_USERID').'&sdkappid='.C('YUN_SDKAPPID').'&random='.rand(100000,999999).'&contenttype=json';
    $set_json = '{
        "UserAttrs":
        [
            {
                "To_Account": "'.$number.'",
                "Attrs": {
                    "uid": "'.$uid.'"
                }
            }
        ]
    }';
    $json = curl($url,$set_json);
    return $json;
}
/**
 * 设置用户vip属性
 * */
function im_set_attr_vip($number,$vip){
    $url = 'https://console.tim.qq.com/v4/openim/im_set_attr?usersig='.get_UserSig(C('YUN_USERID')).'&identifier='.C('YUN_USERID').'&sdkappid='.C('YUN_SDKAPPID').'&random='.rand(100000,999999).'&contenttype=json';
    $set_json = '{
        "UserAttrs":
        [
            {
                "To_Account": "'.$number.'",
                "Attrs": {
                    "vip": "'.$vip.'"
                }
            }
        ]
    }';
    $json = curl($url,$set_json);
    return $json;
}


/**
 * 全员推送
 * */
function all_push($text){
    $random = date('md').rand(1000,9999);
    $random = intval($random);

    $url = 'https://console.tim.qq.com/v4/openim/im_push?usersig='.get_UserSig(C('YUN_USERID')).'&identifier='.C('YUN_USERID').'&sdkappid='.C('YUN_SDKAPPID').'&random='.rand(100000,999999).'&contenttype=json';
    //全员推送
    $json_data = '{
        "MsgRandom": '.$random.',
        "MsgBody": [
            {
                "MsgType": "TIMTextElem",
                "MsgContent": {
                    "Text": "'.$text.'"
                }
            }
        ]
    }';

    $res = curl($url,$json_data);
    return $res;
}

/**
 * 推送给指定uid属性用户
 * */
function single_push($text,$uid){
    $random = date('md').rand(1000,9999);
    $random = intval($random);

    $url = 'https://console.tim.qq.com/v4/openim/im_push?usersig='.get_UserSig(C('YUN_USERID')).'&identifier='.C('YUN_USERID').'&sdkappid='.C('YUN_SDKAPPID').'&random='.rand(100000,999999).'&contenttype=json';

    $json_data = '{
        "MsgRandom": '.$random.',
        "Condition": {
            "AttrsAnd": {
                "uid": "'.$uid.'"
            }
        },
        "MsgBody": [
            {
                "MsgType": "TIMTextElem",
                "MsgContent": {
                    "Text": "'.$text.'"
                }
            }
        ]
    }';
    $res = curl($url,$json_data);
    return $res;
}
/**
 * 推送给指定vip属性用户
 * */
function single_push_vip($text,$vip){
    $random = date('md').rand(1000,9999);
    $random = intval($random);

    $url = 'https://console.tim.qq.com/v4/openim/im_push?usersig='.get_UserSig(C('YUN_USERID')).'&identifier='.C('YUN_USERID').'&sdkappid='.C('YUN_SDKAPPID').'&random='.rand(100000,999999).'&contenttype=json';

    $json_data = '{
        "MsgRandom": '.$random.',
        "Condition": {
            "AttrsAnd": {
                "vip": "'.$vip.'"
            }
        },
        "MsgBody": [
            {
                "MsgType": "TIMTextElem",
                "MsgContent": {
                    "Text": "'.$text.'"
                }
            }
        ]
    }';
    $res = curl($url,$json_data);
    return $res;
}

/**************云通信消息推送封装**************/

/**************黑名单操作**************/
/**
 * 添加黑名单
 * */
function add_black($number,$number_arr,$json_data){
    $url = 'https://console.tim.qq.com/v4/sns/black_list_add?usersig='.get_UserSig(C('YUN_USERID')).'&identifier='.C('YUN_USERID').'&sdkappid='.C('YUN_SDKAPPID').'&random='.rand(100000,999999).'&contenttype=json';

    $res = curl($url,$json_data);
    return $res;
}
/**
 * 删除黑名单
 * */
function delete_black($number,$number_arr,$json_data){
    $url = 'https://console.tim.qq.com/v4/sns/black_list_delete?usersig='.get_UserSig(C('YUN_USERID')).'&identifier='.C('YUN_USERID').'&sdkappid='.C('YUN_SDKAPPID').'&random='.rand(100000,999999).'&contenttype=json';

    $res = curl($url,$json_data);
    return $res;
}
/**************黑名单操作**************/


/**
 * 创建在线成员广播大群（BChatRoom）
 * */
function create_BChatRoom(){
    $url = 'https://console.tim.qq.com/v4/group_open_http_svc/create_group?usersig='.get_UserSig(C('YUN_USERID')).'&identifier='.C('YUN_USERID').'&sdkappid='.C('YUN_SDKAPPID').'&random='.rand(100000,999999).'&contenttype=json';

    $json_data = '{
        "Type": "BChatRoom",
        "Name": "chatRoom"
    }';

    $json = curl($url,$json_data);

    $arr = json_decode($json,true);
    $GroupId = $arr['GroupId'];
    if($arr['ActionStatus'] == 'OK'){
        $count = M('config')->where(['name' => 'GROUPID'])->count();
        if($count){
            M('config')->where(['name' => 'GROUPID'])->setField(['value' => $GroupId]);
        }else{
            $data = [
                'name' => 'GROUPID',
                'type' => 1,
                'title' => '在线成员广播大群id',
                'group' => 4,
                'create_time' => time(),
                'update_time' => time(),
                'status' => 1,
                'value' => $GroupId
            ];
            M('config')->add($data);
        }
    }

    return $GroupId;
}

function send_groud_msg($text){
    $url = 'https://console.tim.qq.com/v4/group_open_http_svc/send_group_system_notification?usersig='.get_UserSig(C('YUN_USERID')).'&identifier='.C('YUN_USERID').'&sdkappid='.C('YUN_SDKAPPID').'&random='.rand(100000,999999).'&contenttype=json';

    $Groupid = C('GROUPID');
    $json_data = '{
        "GroupId": "'.$Groupid.'",
        "Content": "'.$text.'"
    }';

    $json = curl($url,$json_data);
    return $json;
}

